package com.ilovepostcard.view;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.ilovepostcard.R;
import com.ilovepostcard.controller.BaseAsyncTask;
import com.ilovepostcard.controller.OffLineManager;
import com.ilovepostcard.controller.ServerAsyncTask;
import com.ilovepostcard.controller.UserController;
import com.ilovepostcard.controller.server.IServer;
import com.ilovepostcard.controller.server.PostcardResult;
import com.ilovepostcard.controller.server.ServerFactory;
import com.ilovepostcard.data.OffLinePostcard;
import com.ilovepostcard.model.Order;
import com.ilovepostcard.model.OrderItem;
import com.ilovepostcard.model.Postcard;
import com.ilovepostcard.model.User;
import com.ilovepostcard.utils.DrawableManager;

public class PostcardGridView extends LinearLayout {
    
    private static final String SOURCE_TYPE_MY = "my";
    private static final String SOURCE_TYPE_USER = "user";
    private static final String SOURCE_TYPE_RECOMMEND = "recommend";
    private static final String SOURCE_TYPE_INTEREST = "interest";
    private static final String SOURCE_TYPE_SERARCH = "search";
    private static final String SOURCE_TYPE_OFFLINE_BOX = "offline";
    private static final String SOURCE_TYPE_ORDER = "order";

    public static interface OnPostcardClickListener {
        void onClick(final Postcard postcard);
    }
    
    public static interface OnPostcardLongClickListener {
        void onLongClick(final Postcard postcard);
    }
    
    public static interface OnPostcardDataChangeListener
    {
    	void onDataChange();
    }
    
    private TextView mShowMore;
    private TextView mEmpty;
    private String mSourceType;
    private int listSelectorRes;

    private OnPostcardClickListener mOnPostcardClickListener;
    GridView gridView ;
    private OnPostcardLongClickListener mOnPostcardLongClickListener;
    
    private OnPostcardDataChangeListener mOnPostcardDataChangeListener;
    /* page index start from 1 */
    private int mPage = 0;
    
    private ArrayList<Postcard> mPostcardList = new ArrayList<Postcard>();
    private OffLinePostcard[] offLinePostcards;
    
    private PostcardGridAdapter mAdapter;
    private int mLastSelectedPosition = -1;
    private long userId;
    private String keyWord;
    private boolean selectMode = false;
    private boolean hasSingleSelectMode =false;
    private HashMap<Integer, Boolean> selectedMap;
    
    private Order mOrder;
    
    public PostcardGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PostcardSourceType);
        mSourceType = ta.getString(R.styleable.PostcardSourceType_sourceType);
        if (SOURCE_TYPE_OFFLINE_BOX.equals(mSourceType)) {
            setMultiSelectMode();
        }
        listSelectorRes = ta.getResourceId(R.styleable.PostcardSourceType_listSelector, -1);
        ta.recycle();
        inflate();
    }

    public PostcardGridView(Context context) {
        super(context);
        inflate();
    }
    
    public int getSize() {
        return mPostcardList.size();
    }
    
    public void setOrder(Order order) {
        mOrder = order;
    }
    
    public void setUserId(long userId) {
        this.userId = userId;
    }
    
    public void setSingleSelectMode(boolean toSingle)
    {
    	hasSingleSelectMode = toSingle;
    }
    
    public void setMultiSelectMode() {
        selectMode = true;
        selectedMap = new HashMap<Integer, Boolean>();
    }
    
    public void selectAll() {
        int length = offLinePostcards.length;
        for (int i = 0; i < length; i++) {
            selectedMap.put(i, Boolean.TRUE);
        }
        mAdapter.notifyDataSetChanged();
    }
    
    public String[] getSelectedOfflinePostcardName() {
        Set<Integer> positionSet = selectedMap.keySet();
        int length = positionSet.size();
        int[] positions = new int[length];
        int index = 0;
        for (Iterator<Integer> iterator = positionSet.iterator(); iterator.hasNext();) {
            positions[index++] = iterator.next();
        }
        Arrays.sort(positions);
        String[] names = new String[length];
        for (int i = 0; i < length; i++) {
            names[i] = offLinePostcards[positions[i]].getName();
        }
        return names;
    }
    
    public Postcard[] getSelectedPostcard() {
        Set<Integer> positionSet = selectedMap.keySet();
        int length = positionSet.size();
        int[] positions = new int[length];
        int index = 0;
        for (Iterator<Integer> iterator = positionSet.iterator(); iterator.hasNext();) {
            positions[index++] = iterator.next();
        }
        Arrays.sort(positions);
        Postcard[] postcardArray = new Postcard[length];
        for (int i = 0; i < length; i++) {
            postcardArray[i] = mPostcardList.get(positions[i]);
        }
        return postcardArray;
    }
    
    public void setOnPostcardClickListener(OnPostcardClickListener listener) {
        mOnPostcardClickListener = listener;
    }
    
    public void setOnPostcardLongClickListener(OnPostcardLongClickListener listener) {
        mOnPostcardLongClickListener = listener;
    }
    
    public void setOnPostcardDataChangeListener(OnPostcardDataChangeListener l)
    {
    	mOnPostcardDataChangeListener = l;
    }
    
    public void setKeyWord(String key)
    {
    	keyWord = key;
    }

    public void removePostcard(Postcard postcard) {
        mPostcardList.remove(postcard);
        mAdapter.notifyDataSetChanged();
    }
    
    public Object getSelectedItem()
    {
    	
    	PostcardGridAdapter adapter  = (PostcardGridAdapter)gridView.getAdapter();
    	if(mLastSelectedPosition >= 0)
    		return adapter.getItem(mLastSelectedPosition);
    	return null;
    }
    
    public GridView getGridView()
    {
    	return gridView;
    }
    
    private int getEmpetyText() {
        if (SOURCE_TYPE_INTEREST.equals(mSourceType)) {
            return R.string.empty_interest_postcards;
        } else if (SOURCE_TYPE_OFFLINE_BOX.equals(mSourceType)) {
            return R.string.empty_offline;
        } else if (SOURCE_TYPE_MY.equals(mSourceType)) {
            return R.string.empty_my;
        } else if (SOURCE_TYPE_OFFLINE_BOX.equals(mSourceType)) {
            return R.string.empty_offline;
        }
        return R.string.empty_default;
    }
    
	private void inflate() {
        View view = View.inflate(getContext(), R.layout.postcard_grid_view, this);
        mShowMore = (TextView) view.findViewById(R.id.postcard_show_more);
        gridView = (GridView) view.findViewById(android.R.id.list);
        if(listSelectorRes!= -1)
        	gridView.setSelector(listSelectorRes);

        mAdapter = new PostcardGridAdapter();
        gridView.setAdapter(mAdapter);
        mEmpty = (TextView) view.findViewById(android.R.id.empty);
        // will set empty text in loadNextPage
        /*mEmpty.setText(getEmpetyText());*/
        gridView.setEmptyView(mEmpty);
        gridView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (selectMode) {
                    if (selectedMap.get(position) == null) {
                        selectedMap.put(position, Boolean.TRUE);
                    }
                    else {
                        selectedMap.remove(position);
                    }
                    mAdapter.notifyDataSetChanged();
                    return;
                }

               mAdapter.notifyDataSetChanged();
                
            	mLastSelectedPosition = position;
                if (mOnPostcardClickListener != null) {
                    Postcard postcard = mPostcardList.get(position);
                    mOnPostcardClickListener.onClick(postcard);
                }
            }
            
        });
        gridView.setOnItemLongClickListener(new OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view,
                    int position, long id) {
                if (mOnPostcardLongClickListener != null) {
                    Postcard postcard = mPostcardList.get(position);
                    mOnPostcardLongClickListener.onLongClick(postcard);
                    return true;
                }
                return false;
            }
            
        });
        
        gridView.setOnItemSelectedListener(new OnItemSelectedListener()
        {

			@Override
			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				
				
			}

			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// TODO Auto-generated method stub
				
			}
        	
        });
        mShowMore.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                loadNextPage();
            }
        });
        
    }
	
	public boolean isLoaded() {
	    return mPage > 0;
	}
    
	public void reload() {
	    mPage = 0;
	    selectedMap.clear();
	    mPostcardList.clear();
	    mShowMore.setVisibility(GONE);
	    loadNextPage();
	}
	
	public void loadNextPage(final Runnable onLoaded) {
		if (!isLoaded()) {
			showEmpty(false);
		}
	    if (SOURCE_TYPE_OFFLINE_BOX.equals(mSourceType) && !isLoaded()) {
            mPage = 1;
            offLinePostcards = OffLineManager.getInstance().getAllOffLinePostcard();
            if (offLinePostcards != null && offLinePostcards.length > 0) {
                int length = offLinePostcards.length;
                for (int i = 0; i < length; i++) {
                    OffLinePostcard offLinePostcard = offLinePostcards[i];
                    Postcard postcard = new Postcard();
                    postcard.isOffline = true;
                    postcard.offlineName = offLinePostcard.getName();
                    postcard.imagePath = offLinePostcard.getImagePath();
                    mPostcardList.add(postcard);
                }
                
            }
            if (mPostcardList.size()> 0) {
                mShowMore.setVisibility(VISIBLE);
            }
            mAdapter.notifyDataSetChanged();
            if (onLoaded != null) {
                onLoaded.run();
            }
            showEmpty(true);
            return;
        }
        if (SOURCE_TYPE_ORDER.equals(mSourceType) && !isLoaded()) {
            
//            new BaseAsyncTask() {
//
//                ArrayList<Postcard> orderPostcards = new ArrayList<Postcard>();
//                
//                ProgressDialog pd;
//                
//                boolean success = true;
//                
//                @Override
//                protected void _doInBackground() {
//                    OrderItem[] items = mOrder.Items;
//                    if (items != null && items.length > 0) {
//                        for (int i = 0; i < items.length; i++) {
//                            PostcardResult result = ServerFactory.getServer().getPostcardInfo(items[i].PostcardID);
//                            if (!result.isSuccess()) {
//                                success = false;
//                                break;
//                            }
//                            orderPostcards.add(result.getPostcardInfo());
//                        }
//                    }
//                }
//
//                @Override
//                protected void _onPostExecute() {
//                    if (success) {
//                        mPostcardList.addAll(orderPostcards);
//                        if (mPostcardList.size()> 0) {
//                            mShowMore.setVisibility(VISIBLE);
//                        }
//                        mAdapter.notifyDataSetChanged();
//                        mPage = 1;
//                    } else {
//                        Toast.makeText(getContext(), "获取订单明信片失败，请重试", Toast.LENGTH_SHORT).show();
//                        mShowMore.setText("重新加载");
//                        mPage = 0;
//                        mShowMore.setVisibility(VISIBLE);
//                    }
//                    try {
//                        pd.dismiss();
//                    } catch (Throwable e) {
//
//                    }
//                }
//
//                @Override
//                protected void _onPreExecute() {
//                    pd = new ProgressDialog(getContext());
//                    pd.setMessage(getContext().getString(R.string.loading_data));
//                    pd.show();
//                    mShowMore.setVisibility(GONE);
//                }
//                
//            }.execute();
            return;
        }
        new ServerAsyncTask(getContext()) {
            
            @Override
            protected void onSuccess(PostcardResult result) {
            	showEmpty(true);
                if((result.getPostcardList()==null ||  result.getPostcardList().size()== 0))
                {
                    if(mPage>0)
                        Toast.makeText(context, "没有更多啦～", Toast.LENGTH_SHORT).show();
                    else
                        mShowMore.setVisibility(GONE);
                    mPage++;
                    return;
                }
                
                mPage++;
                mPostcardList.addAll(result.getPostcardList());
                if (mPostcardList.size()> 0) {
                    mShowMore.setVisibility(VISIBLE);
                }
                mAdapter.notifyDataSetChanged();
                if(mOnPostcardDataChangeListener != null)
                    mOnPostcardDataChangeListener.onDataChange();
            }
            
            @Override
            protected PostcardResult doRequest() {
                User user = UserController.getLoginUser(getContext());
                long uid = user.UserID;
                int nextPage = mPage + 1;
                int pageSize = 15;
                IServer server = ServerFactory.getServer();
                PostcardResult result = null;
                if (SOURCE_TYPE_RECOMMEND.equals(mSourceType)) {
                    result = server.getRecommendPostcard(uid, nextPage, pageSize);
                } else if (SOURCE_TYPE_INTEREST.equals(mSourceType)) {
                    result = server.getFriendPostcard(uid, nextPage, pageSize);
                } else if (SOURCE_TYPE_MY.equals(mSourceType)) {
                    result = server.getMyPostcard(uid, nextPage, pageSize);
                } else if (SOURCE_TYPE_USER.equals(mSourceType)) {
                    result = server.getMyPostcard(userId, nextPage, pageSize);
                }
                else if(SOURCE_TYPE_SERARCH.equals(mSourceType))
                {
                     result = server.searchPostcard(keyWord, nextPage, pageSize);
                }
                return result;
            }
        }.execute();
        
	}
	
    public void loadNextPage() {
        loadNextPage(null);
    }
    
    private void showEmpty(boolean show) {
    	mEmpty.setText(show ? getContext().getString(getEmpetyText()) : "");
    }
    
    private class PostcardGridAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return mPostcardList.size();
        }

        @Override
        public Object getItem(int position) {
            return mPostcardList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            PostcardWidget pWidget = null;
            
            if (convertView != null)
                pWidget = (PostcardWidget) convertView;
            else
                pWidget = new PostcardWidget(getContext());
            
            final PostcardWidget pw = pWidget;
            pw.setGravity(Gravity.CENTER);
            Postcard postcard = mPostcardList.get(position);
            
            if (postcard.isOffline) {
            	DrawableManager.getInstance().fetchLocalFileDrawableOnThread(postcard.imagePath, pw.getPostcardImageView());
//                pw.getPostcardImageView().setImageDrawable(Drawable.createFromPath(postcard.imagePath));
                pw.setSelected(selectedMap.get(position) != null);
            } else {
                if (postcard.Status == 1) {
                    /* deleted */
                    pw.setPostcardImage(R.drawable.discover_card_deleted);
                } else {
                    if (!DrawableManager.getInstance().fetchDrawableOnThread(postcard.ThumImgUrl, pw.getPostcardImageView()))
                        pw.setPostcardImage(R.drawable.discover_card_loading);
                }
                
                if(hasSingleSelectMode || selectMode)
                {
                     pw.setSelected(selectedMap.containsKey(new Integer(position)));
                }
            }
            
            return pw;
        }
        
    }
    
//    protected abstract ArrayList<Postcard> getPage(int page);
}
